<?php  
import('miho.db.*');
import('miho.db.table.fields.*');
import('miho.db.table.key.*');
import('miho.db.table.exception.*');
import('miho.db.logger.*');
/**
* Database table abstraction
*/
abstract class Table implements ArrayAccess
{
  protected $_connection;
  
  protected $_name;
  public function getName(){
    return $this->_name;
  }
  
  protected $_fields = array();
  public function getFields(){
    return $_fields;
  }
  
  protected $_primaryKey;
  
  protected $_keys = array();
  
  public function __construct(){
    $this->_connection = Connection::getActiveConnection();
    $this->create();
  }
  
  protected function _createField($field){
    $field->setTable($this);
    $this->_fields[$field->getName()] = $field;
  }
  
  protected function _addKey($key){
    $this->_keys[$key->getName()] = $key;
  }
  
  public function select2(Criteria $c){
    return $this->_connection->query($c->generateSql())->fetchAll();
  }
  
  public function select(){
   $args = func_get_args();
   
   $sql = 'SELECT ';
   
   $fields = array();
   
   foreach ($args as $arg) {
     if(is_a($arg,'BaseTableField')){
      $fields[] = $arg;
     }
   }
   
   if(sizeof($fields)==0){
    $fields = $this->_fields;     
   }
   $last = end($fields);
   foreach ($fields as $field) {
      $sql.=$field->getName().($field!=$last ? ',' : '').' ';
   }
  
   $sql.=' FROM '.$this->_name;
   $sql.=' ;';
   
   //var_dump($sql);
   Logger::getLogger()->dump($sql);
   $stmt = $this->_connection->query($sql);
   return $stmt->fetchAll();
  }
  
  public function insert($data){
    if( (!is_array($data)) && (!is_object($data))){
      throw new Exception('Wrong data');
    }
    
    $invalidFields = array();
    $completeFields = array();
    foreach ($data as $key => $value) {
      if(!isset($this->_fields[$key])){
        continue;
      }
      $field = $this[$key];
      $field->setValue($value);
      if(!$field->isValid()){
        $invalidFields[] = $field;
      }
    }
    
    if(sizeof($invalidFields)>0){
      throw new ValidationException($invalidFields);
      //throw new Exception(var_export($invalidFields,true));
    }
    
    $sql = 'INSERT INTO '.$this->_name.' SET ';
    $last = end($this->_fields);
    foreach ($this->_fields as $field) {
      $sql.=$field->getName().'="'.$field->getValue().'"'.(($field==$last) ? '; ' : ', ');
    }
    Logger::getLogger()->dump($sql);
    $pdo = $this->_connection->getPDO();
    $stmt = $pdo->prepare($sql);
    $stmt->execute();
    Logger::getLogger()->dump($stmt->errorInfo());
  }
  
  public function delete(){
    
  }
  
  /// ARRAY ACCESS
  public function offsetExists($offset){
    return isset($this->_fields[$offset]);
  }
  
  public function offsetGet($offset){
   return isset($this->_fields[$offset]) ? $this->_fields[$offset] : null;
  }
  
  public function offsetSet($offset, $value){
    throw new Exception('Action denied');
  }
  
  public function offsetUnset($offset){
    throw new Exception('Action denied');
  }
  
  /**
   * This function describes table schema.
   *
   * @return void
   * @author miho
   */
  abstract function create();
  
  abstract function drop();
  
  const EOL = "\n";
  
  public function up(){
    $sql= 'CREATE TABLE IF NOT EXISTS `'.$this->_name.'`  '.self::EOL.'('.self::EOL;
    $last = end($this->_fields);
    foreach ($this->_fields as $field) {
      $sql.="\t".$field->generateCreateScript() . ',' . self::EOL;  
    }
    $last = end($this->_keys);
    foreach ($this->_keys as $key) {
      $sql.= "\t" . $key->generateCreateScript() . ($key!=$last ? ',' : '') . self::EOL;
    }
    $sql.=') Type=InnoDB'. self::EOL;
    
    $this->_connection->query($sql);
  }
  
  public function down(){
    echo ('DROP TABLE ');
  }
  
}


?>